﻿namespace PomodoroTool.Core
{
    #region

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Text.RegularExpressions;

    #endregion

    public class TaskFormatter
    {
        #region Constants and Fields

        private const string ActiveTaskTag = "[T]";

        private const string CompleteRegex = @"\[d\]";

        private const string CompleteTag = @"[d]";

        private const string PomodoroRegex = @"\[p\]";

        private const string PomodoroTag = @"[p]";

        private const string TaskTag = "[t]";

        #endregion

        #region Public Methods

        public string FormatTasks(IEnumerable<PomodoroController.Task> _tasks)
        {
            if (_tasks == null || !_tasks.Any())
            {
                return string.Empty;
            }

            var sb = new StringBuilder();

            var width = GetMaxWidth(_tasks);

            foreach (var task in _tasks)
            {
                IEnumerable<string> lines = task.Lines;
                sb.AppendFormat(
                    "{0} {1} {2}{3}", 
                    task.Active ? ActiveTaskTag : TaskTag, 
                    (lines.FirstOrDefault() ?? string.Empty).PadRight(width), 
                    GetBadges(task), 
                    Environment.NewLine);

                foreach (var line in lines.Skip(1))
                {
                    sb.AppendFormat(String.Concat(new string(' ', TaskTag.Length + 1), line, Environment.NewLine));
                }
                sb.AppendLine();
            }
            return sb.ToString();
        }

        public IEnumerable<PomodoroController.Task> ParseText(string task)
        {
            var r = new StringReader(task);
            var lines = new List<string>();
            string line;
            while ((line = r.ReadLine()) != null)
            {
                lines.Add(line);
            }
            return this.ParseText(lines);
        }

        #endregion

        #region Methods

        private string ClearFromTags(string aLine)
        {
            var tags = new[] { PomodoroRegex, CompleteRegex };
            return tags.Aggregate(aLine, (current, re) => Regex.Replace(current, re, String.Empty));
        }

        private int CountPomodoros(string line)
        {
            return Regex.Matches(line, PomodoroRegex).Count;
        }

        private string GetBadges(PomodoroController.Task task)
        {
            var pomodoros = Enumerable.Range(1, task.Pomodoros).Select(q => PomodoroTag).ToList();
            if (task.Completed)
            {
                pomodoros.Add(CompleteTag);
            }
            return String.Join(" ", pomodoros.ToArray());
        }

        private int GetMaxWidth(IEnumerable<PomodoroController.Task> _tasks)
        {
            IEnumerable<string> allLines = _tasks.SelectMany(t => t.Lines);
            if (allLines.Any())
            {
                return allLines.Max(q => q.Length);
            }
            return 0;
        }

        private IEnumerable<PomodoroController.Task> ParseText(IEnumerable<string> taskLines)
        {
            List<PomodoroController.Task> _tasks = new List<PomodoroController.Task>();
            int lineNo = 0;
            PomodoroController.Task currentTask = null;
            foreach (var line in taskLines)
            {
                var aLine = line.Trim();
                if (aLine.StartsWith(TaskTag) || aLine.StartsWith(ActiveTaskTag))
                {
                    currentTask = new PomodoroController.Task
                        { LineFound = lineNo, Active = aLine.StartsWith(ActiveTaskTag) };
                    _tasks.Add(currentTask);
                    aLine = aLine.Substring(TaskTag.Length);
                }

                if (currentTask != null && !String.IsNullOrEmpty(aLine))
                {
                    currentTask.AddLine(ClearFromTags(aLine).Trim());
                    currentTask.Pomodoros += this.CountPomodoros(aLine);
                    currentTask.Completed |= Regex.Matches(aLine, CompleteRegex).Count > 0;
                }

                lineNo++;
            }
            return _tasks;
        }

        #endregion
    }
}